<?php
/**
 * 获取链接内容类
 *
 * @package Z-BlogPHP
 * @subpackage ClassLib/Network/Networkfile_get_contents 网络连接
 */
class Networkfile_get_contents implements iNetwork
{
  private $readyState = 0; //状态
  private $responseBody = null; //返回的二进制
  private $responseStream = null; //返回的数据流
  private $responseText = ''; //返回的数据
  private $responseXML = null; //尝试把responseText格式化为XMLDom
  private $status = 0; //状态码
  private $statusText = ''; //状态码文本
  private $responseVersion = ''; //返回的HTTP版体
  private $option = array();
  private $url = '';
  private $postdata = array();
  private $httpheader = array();
  private $responseHeader = array();
  private $isgzip = false;
  private $maxredirs = 0;
  private $parsed_url = array();
  private $__isBinary = false;
  private $__boundary = '';
  /**
   * @param $property_name
   * @param $value
   * @throws Exception
   */
  public function __set($property_name, $value)
  {
    throw new Exception($property_name . ' readonly');
  }
  /**
   * @param $property_name
   * @return mixed
   */
  public function __get($property_name)
  {
    if (strtolower($property_name) == 'responsexml') {
      $w = new DOMDocument();
      return $w->loadXML($this->responseText);
    } elseif (strtolower($property_name) == 'scheme' || strtolower($property_name) == 'host' || strtolower($property_name) == 'port' || strtolower($property_name) == 'user' || strtolower($property_name) == 'pass' || strtolower($property_name) == 'path' || strtolower($property_name) == 'query' || strtolower($property_name) == 'fragment') {
      if (isset($this->parsed_url[strtolower($property_name)])) {
        return $this->parsed_url[strtolower($property_name)];
      } else {
        return null;
      }
    } else {
      return $this->$property_name;
    }
  }
  /**
   *
   */
  public function abort()
  {
  }
  /**
   * @return string
   */
  public function getAllResponseHeaders()
  {
    return implode("\r\n", $this->responseHeader);
  }
  /**
   * @param $bstrHeader
   * @return string
   */
  public function getResponseHeader($bstrHeader)
  {
    $name = strtolower($bstrHeader);
    foreach ($this->responseHeader as $w) {
      if (strtolower(substr($w, 0, strpos($w, ':'))) == $name) {
        return substr(strstr($w, ': '), 2);
      }
    }
    return '';
  }
  /**
   * @param $resolveTimeout
   * @param $connectTimeout
   * @param $sendTimeout
   * @param $receiveTimeout
   */
  public function setTimeOuts($resolveTimeout, $connectTimeout, $sendTimeout, $receiveTimeout)
  {
  }
  /**
   * @param $bstrMethod
   * @param $bstrUrl
   * @param bool $varAsync
   * @param string $bstrUser
   * @param string $bstrPassword
   * @return bool
   * @throws Exception
   */
  public function open($bstrMethod, $bstrUrl, $varAsync = true, $bstrUser = '', $bstrPassword = '')
  {
    //Async无用
    //初始化变量
    $this->reinit();
    $method                 = strtoupper($bstrMethod);
    $this->option['method'] = $method;
    $this->parsed_url       = parse_url($bstrUrl);
    if (!$this->parsed_url) {
      throw new Exception('URL Syntax Error!');
    } else {
      if ($bstrUser != '') {
        $bstrUrl = substr($bstrUrl, 0, strpos($bstrUrl, ':')) . '://' . $bstrUser . ':' . $bstrPassword . '@' . substr($bstrUrl, strpos($bstrUrl, '/') + 2);
      }
      $this->url = $bstrUrl;
      if (!isset($this->parsed_url['port'])) {
        if ($this->parsed_url['scheme'] == 'https') {
          $this->parsed_url['port'] = 443;
        } else {
          $this->parsed_url['port'] = 80;
        }
      }
    }
    return true;
  }
  /**
   * @param string $varBody
   */
  public function send($varBody = '')
  {
    $data = $varBody;
    if (is_array($data)) {
      $data = http_build_query($data);
    }
    if ($this->option['method'] == 'POST') {
      if ($data == '') {
        $data = $this->__buildPostData(); //http_build_query($this->postdata);
      }
      $this->option['content'] = $data;
      if (!isset($this->httpheader['Content-Type'])) {
        if ($this->__isBinary) {
          $this->httpheader['Content-Type'] = 'Content-Type:  multipart/form-data; boundary=' . $this->__boundary;
        } else {
          $this->httpheader['Content-Type'] = 'Content-Type: application/x-www-form-urlencoded';
        }
      }
      $this->httpheader['Content-Length'] = 'Content-Length: ' . strlen($data);
    }
    $this->option['header'] = implode("\r\n", $this->httpheader);
    //$this->httpheader[] = 'Referer: ' . 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    if ($this->maxredirs > 0) {
      $this->option['follow_location'] = true;
      //补一个数字 要大于1才跳转
      $this->option['max_redirects']   = $this->maxredirs + 1;
    } else {
      $this->option['follow_location'] = 0;
      $this->option['max_redirects']   = 0;
    }
    ZBlogException::SuspendErrorHook();
    $http_response_header = null;
    $this->responseText   = file_get_contents(($this->isgzip == true ? 'compress.zlib://' : '') . $this->url, false, stream_context_create(array(
      'http' => $this->option
    )));
    $this->responseHeader = $http_response_header;
    ZBlogException::ResumeErrorHook();
    foreach ($this->responseHeader as $key => $value) {
      if (strpos($value, 'HTTP/') === 0) {
        if (isset($this->responseHeader[$key])) {
          $this->statusText = $this->responseHeader[$key];
          $a                = explode(' ', $this->statusText);
          if (isset($a[0])) {
            $this->responseVersion = $a[0];
          }
          if (isset($a[1])) {
            $this->status = $a[1];
          }
          unset($this->responseHeader[$key]);
        }
      }
    }
  }
  /**
   * @param $bstrHeader
   * @param $bstrValue
   * @param bool $append
   * @return bool
   */
  public function setRequestHeader($bstrHeader, $bstrValue, $append = false)
  {
    if ($append == false) {
      $this->httpheader[$bstrHeader] = $bstrHeader . ': ' . $bstrValue;
    } else {
      if (isset($this->httpheader[$bstrHeader])) {
        $this->httpheader[$bstrHeader] = $this->httpheader[$bstrHeader] . $bstrValue;
      } else {
        $this->httpheader[$bstrHeader] = $bstrHeader . ': ' . $bstrValue;
      }
    }
    return true;
  }
  /**
   * @param $bstrItem
   * @param $bstrValue
   */
  private function add_postdata($bstrItem, $bstrValue)
  {
    $this->postdata[$bstrItem] = array(
      'data' => $bstrValue,
      'type' => 'text'
    );
  }
  /**
   * @param string $name
   * @param string $entity
   * @return mixed
   */
  public function addBinary($name, $entity, $filename = null, $mime = '')
  {
    $this->__isBinary = true;
    $return           = array();
    $return['type']   = 'binary';
    if (is_file($entity)) {
      $return['data']     = file_get_contents($entity);
      $return['filename'] = ($filename === null ? basename($entity) : $filename);
      if ($mime == '') {
        if (function_exists('mime_content_type')) {
          $mime = mime_content_type($entity);
        } elseif (function_exists('finfo_open')) {
          $finfo = finfo_open(FILEINFO_MIME);
          $mime  = finfo_file($finfo, $name);
          finfo_close($finfo);
        } else {
          $mime = 'application/octet-stream';
        }
      }
    } else {
      $name               = basename($name);
      $return['data']     = $entity;
      $return['filename'] = ($filename === null ? basename($entity) : $filename);
      $mime               = $mime == '' ? 'application/octet-stream' : $mime;
    }
    $return['mime']        = $mime;
    $this->postdata[$name] = $return;
  }
  /**
   * @param string $name
   * @param string $entity
   * @return mixed
   */
  public function addText($name, $entity)
  {
    return $this->add_postdata($name, $entity);
  }
  /**
   * @return string
   */
  private function __buildPostData()
  {
    if (!$this->__isBinary) {
      $array = array();
      foreach ($this->postdata as $name => $value) {
        $array[$name] = $value['data'];
      }
      return http_build_query($array);
    }
    $this->__buildBoundary();
    $boundary = $this->__boundary;
    $data     = '';
    foreach ($this->postdata as $name => $value) {
      $data .= "\r\n";
      $content = $value['data'];
      $data .= "--{$boundary}\r\n";
      $data .= "Content-Disposition: form-data; ";
      if ($value['type'] == 'text') {
        $data .= 'name="' . $name . '"' . "\r\n\r\n";
        $data .= $content; // . "\r\n";
        //$data .= "--{$boundary}";
      } else {
        $filename = $value['filename'];
        $mime     = $value['mime'];
        $data .= 'name="' . $name . '"; filename="' . $filename . '"' . "\r\n";
        $data .= "Content-Type: $mime\r\n";
        $data .= "\r\n$content"; //"\r\n";
        //$data .= "--{$boundary}";
      }
    }
    $data .= "\r\n--{$boundary}--\r\n";
    return $data;
  }
  /**
   * Build Boundary
   */
  private function __buildBoundary()
  {
    $boundary = '----ZBLOGPHPBOUNDARY';
    $boundary .= substr(md5(time()), 8, 16);
    $this->__boundary = $boundary;
  }
  /**
   *
   */
  private function reinit()
  {
    // global $zbp;
    $this->readyState     = 0; //状态
    $this->responseBody   = null; //返回的二进制
    $this->responseStream = null; //返回的数据流
    $this->responseText   = ''; //返回的数据
    $this->responseXML    = null; //尝试把responseText格式化为XMLDom
    $this->status         = 0; //状态码
    $this->statusText     = ''; //状态码文本
    $this->__isBinary     = false;
    $this->__boundary     = '';
    $this->option         = array();
    $this->url            = '';
    $this->postdata       = array();
    $this->httpheader     = array();
    $this->responseHeader = array();
    // $this->setRequestHeader('User-Agent', 'Mozilla/5.0 (' . $zbp->cache->system_environment . ') Z-BlogPHP/' . $GLOBALS['blogversion']);
    $this->setMaxRedirs(1);
  }
  /**
   * 启用Gzip
   */
  public function enableGzip()
  {
    if (extension_loaded('zlib')) {
      $this->isgzip = true;
    }
  }
  /**
   * @param int $n
   */
  public function setMaxRedirs($n = 0)
  {
    $this->maxredirs = $n;
  }
}
